package com.jike.jkgame.data;

import java.util.ArrayList;
import java.util.List;

public class TreeNode<T> {
	
	private T data_;
	
	private List<TreeNode<T>> children_;
	
	private TreeNode<T> parent_;
	
	public TreeNode() {
		children_ = new ArrayList<TreeNode<T>>();
	}
	
	public TreeNode(T data) {
		this();
		setData(data);
	}
	
	public TreeNode<T> getPartent() {
		return parent_;
	}
	
	public List<TreeNode<T>> getChildren() {
		return children_;
	}
	
	public TreeNode<T> getChildAt(int index) throws IndexOutOfBoundsException {
		return children_.get(index);
	}
	
	public int getNumberOfChildren() {
		return children_.size();
	}
	
	public boolean hasChildren() {
		return !children_.isEmpty();
	}
	
	public void setChildren(List<TreeNode<T>> children) {
		for(TreeNode<T> child : children) {
			child.parent_ = this;
		}
		children_ = children;
	}
	
	public void addChild(TreeNode<T> child) {
		child.parent_ = this;
		children_.add(child);
	}
	
	public void addChildAt(int index, TreeNode<T> child) throws IndexOutOfBoundsException {
		child.parent_ = this;
		children_.add(index, child);
	}
	
	public void removeChildren() {
		children_ = new ArrayList<TreeNode<T>>();
	}
	
	public void removeChildAt(int index) throws IndexOutOfBoundsException {
		children_.remove(index);
	}
	
	public void setData(T data) {
		data_ = data;
	}
	
	public T getData() {
		return data_;
	}
	
	@Override
	public String toString() {
		return getData().toString();
	}
	
	@Override
	public boolean equals(Object o) {
		if(this == o) {
			return true;
		}
		if(o == null) {
			return false;
		}
		if(getClass() != o.getClass()) {
			return false;
		}
		TreeNode<?> that = (TreeNode<?>)o;
		if(data_ == null) {
			if(that.data_ != null) {
				return false;
			}
		} else if(!data_.equals(that.data_)) {
			return false;
		}
		return true;
	}
	
	@Override
	public int hashCode() {
		return 31 + (data_ != null ? data_.hashCode() : 0);
	}
	
	public String toStringVerbose() {
		StringBuilder sb =  new StringBuilder();
		sb.append(getData().toString()).append( ":[");
		boolean first = true;
		for(TreeNode<T> node : getChildren()) {
			if(first) {
				sb.append(node.getData().toString());
				first = false;
			} else {
				sb.append(", ").append(node.getData().toString());
			}
		}
		return sb.toString();
	}
}
